home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / TextFormatter.C < prev    next >
C/C++ Source or Header  |  1992-08-26  |  7KB  |  345 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "TextFormatter.h"
  6.  
  7. #include "Class.h"
  8. #include "Text.h"
  9. #include "TextPainter.h"
  10. #include "ObjArray.h"
  11. #include "Math.h"
  12.   
  13. //---- TextFormatter -----------------------------------------------------------
  14.  
  15. NewAbstractMetaImpl(TextFormatter,Object, (TP(lines)));
  16.  
  17. ObjArray *TextFormatter::lines;
  18. int TextFormatter::nLines;
  19.  
  20. ONEXIT(TextFormatter)
  21. {
  22.     TextFormatter::Free();
  23. }
  24.     
  25. TextFormatter::TextFormatter()
  26. {
  27.     if (lines == 0)
  28.     lines= new ObjArray(32);
  29. }
  30.  
  31. void TextFormatter::Free()
  32. {
  33.     if (lines) {
  34.     lines->FreeAll();
  35.     SafeDelete(lines);
  36.     }
  37. }
  38.  
  39. int TextFormatter::Format(Text *t, TextPainter *tp, int w, int from, int to)
  40. {
  41.     nLines= 0;
  42.     DoFormat(t, tp, w, from, to);
  43.     return nLines;
  44. }
  45.  
  46. void TextFormatter::AddBreak(
  47.     Text *t, TextPainter *tp, int from, int to, LineDesc &ld
  48. )
  49. {
  50.     if(nLines >= lines->Size())
  51.     lines->Expand((nLines)*2);
  52.     LineMark *lm= (LineMark*)lines->At(nLines);
  53.     if (lm == 0) {
  54.     lm= new LineMark;
  55.     lines->AtPut(nLines, lm);
  56.     }
  57.     tp->LineHeight(t, ld, from, to);
  58.     lm->ChangeMark(from, to-from, ld);
  59.     ld.Reset();
  60.     nLines++;
  61. }
  62.  
  63. ObjArray *TextFormatter::GetLines()
  64. {
  65.     return lines;
  66. }
  67.  
  68. void TextFormatter::DoFormat(Text *, TextPainter *, int, int, int)
  69. {
  70.     AbstractMethod("DoFormat");
  71. }
  72.  
  73. //---- SimpleFormatter ---------------------------------------------------------
  74.  
  75. NewMetaImpl0(SimpleFormatter,TextFormatter);
  76.  
  77. SimpleFormatter::SimpleFormatter() : TextFormatter()
  78. {
  79. }
  80.  
  81. void SimpleFormatter::DoFormat(Text *t, TextPainter *tp, int, int from, int to)
  82. {
  83.     AutoTextIter next(t, from, to);
  84.     register int ch, pos;
  85.     int start= from; 
  86.     int wx= 0;
  87.     int cx= 0;
  88.     LineDesc maxld, ld;
  89.     
  90.     while (TRUE) { 
  91.     ch= next->Token(&wx, &ld);
  92.     maxld.Max(ld);
  93.     if (ch == cEOT) {
  94.         pos= next->GetPos();
  95.         if (start != pos)
  96.         AddBreak(t, tp, start, pos, maxld); 
  97.         return;
  98.     }
  99.     if (ch == '\t') 
  100.         wx= tp->Tabulate(t, cx, next->GetLastPos(), start);
  101.     if (Text::IsBreak(ch)) {
  102.         AddBreak(t, tp, start, next->GetPos(), maxld);
  103.         start= next->GetPos();
  104.         cx= 0;
  105.     } else 
  106.         cx+= wx;
  107.     }
  108. }
  109.  
  110. //---- class FoldingFormatter --------------------------------------------------
  111.  
  112. NewMetaImpl(FoldingFormatter,TextFormatter, (T(width), TP(text), T(start),
  113.                 T(end), T(nWords),
  114.                 T(wx), T(cx)));
  115.  
  116. FoldingFormatter::FoldingFormatter() : TextFormatter()
  117. {
  118. }
  119.  
  120. void FoldingFormatter::DoFormat(Text *t, TextPainter *tp, int w, int from, int to)
  121. {
  122.     AutoTextIter next(t, from, to);
  123.     text= t;
  124.     register int ch, pos;
  125.     start= from; 
  126.     nWords= wx= cx= 0;
  127.     LineDesc maxld, ld;
  128.     
  129.     width= tp->GetFormatWidth(t, from, w);
  130.     
  131.     while (TRUE) { 
  132.     ch= next->Token(&wx, &ld);
  133.     
  134.     // break character
  135.     if (wx > width && (next->GetPos()-next->GetLastPos() == 1)) {      
  136.         Break(tp, start, next->GetLastPos(), maxld, w);
  137.         BreakCharacter(t, tp, start, maxld, w);
  138.         continue;
  139.     }
  140.     // word has to be folded on several lines
  141.     if (cx + wx > width && nWords == 0) {
  142.         end= next->GetPos();
  143.         BreakWord(t, tp, maxld, w);
  144.         wx= 0;
  145.     }
  146.  
  147.     if (ch == cEOT) {
  148.         maxld.Max(ld);
  149.         pos= next->GetPos();
  150.         if (start != pos)
  151.         AddBreak(t, tp, start, pos, maxld); 
  152.         return;
  153.     }
  154.  
  155.     if (ch == '\t' || ch == ' ' || Text::IsBreak(ch)) {
  156.         maxld.Max(ld);
  157.         if (ch == '\t') 
  158.         wx= tp->Tabulate(t, cx, next->GetLastPos(), start);
  159.         if (Text::IsBreak(ch) || (cx + wx > width)) 
  160.         Break(tp, start, next->GetPos(), maxld, w);
  161.         else {
  162.         cx+= wx;
  163.         nWords++;
  164.         }
  165.     } else if (cx + wx > width) { 
  166.         Break(tp, start, next->GetLastPos(), maxld, w);
  167.         maxld= ld;
  168.         cx= wx;
  169.     } else {
  170.         maxld.Max(ld);
  171.         cx+= wx;
  172.         nWords++;
  173.     }
  174.     }
  175. }
  176.  
  177. void FoldingFormatter::Break(
  178.     TextPainter *tp, int from, int to, LineDesc &maxld, int w
  179. )
  180. {
  181.     AddBreak(text, tp, from, to, maxld);
  182.     start= end= to;
  183.     width= tp->GetFormatWidth(text, end, w);
  184.     cx= 0;
  185.     nWords= 0;
  186. }
  187.  
  188. void FoldingFormatter::BreakWord(Text *, TextPainter *tp, LineDesc &maxld, int w)
  189. {
  190.     int l= 0, cw, ccw= 0; 
  191.     AutoTextIter ti(text, start, end); // avoid nesting of nextc
  192.     LineDesc ld;
  193.     maxld.Reset();
  194.     while (ti(&cw, &ld) != cEOT) { 
  195.     if (ccw + cw > width) {
  196.         end= ti->GetPos();
  197.         ccw= cw;
  198.         Break(tp, start, end-1, maxld, w); 
  199.         maxld= ld;
  200.     } else {      
  201.         maxld.Max(ld);
  202.         ccw+= cw;
  203.     }
  204.     }
  205.     cx= ccw;
  206.     end= ti->GetPos();
  207.  
  208. void FoldingFormatter::BreakCharacter(Text*, TextPainter *tp, int at, LineDesc &maxld, int w)
  209. {
  210.     LineDesc ld;
  211.     int cw;
  212.     AutoTextIter ti(text, at, at+1); 
  213.     maxld.Reset();
  214.     ti(&cw, &maxld);
  215.     Break(tp, at, at+1, maxld, w);
  216. }
  217.  
  218. //---- abstract class TextPager ------------------------------------------
  219.  
  220. NewMetaImpl0(TextPager, Object);
  221.     
  222. TextPager::TextPager()
  223. {
  224. }
  225.  
  226. Rectangle TextPager::NextPageBreak(int, Rectangle pgr, StaticTextView *)
  227. {
  228.     return pgr;
  229. }
  230.     
  231. void TextPager::Repaginate(int)
  232. {
  233. }
  234.  
  235. //---- LinePager ---------------------------------------------------------
  236.  
  237. #include "StaticTView.h"
  238.  
  239. LinePager::LinePager()
  240. {
  241. }
  242.     
  243. Rectangle LinePager::NextPageBreak(int, Rectangle r, StaticTextView *tv)
  244. {
  245.     int sl= tv->PointToLine(r.origin-tv->GetInnerOrigin());
  246.     int h= tv->LineToPoint(sl, FALSE, FALSE).y-r.origin.y;
  247.     int sh= h;
  248.     int ph= r.Height();
  249.     Text *text= tv->GetText();
  250.     
  251.     for (int i= sl; i < tv->Lines(); i++) {
  252.     int dh= tv->LineHeight(i);
  253.     if (h + dh > ph) { // possible page break
  254.         if (h != sh)  // page is not empty
  255.         r.extent.y= h;
  256.         break;
  257.     }             
  258.     h+= dh;
  259.     } 
  260.     return r;
  261. }
  262.  
  263. //---- LineDesc --------------------------------------------------------
  264.  
  265. LineDesc::LineDesc(int b, int h)
  266. {
  267.     lnAscent= b;
  268.     lnHeight= h;
  269.  
  270. void LineDesc::FromFont(Font *f)
  271.     lnAscent= f->Ascender();
  272.     lnHeight= f->Spacing();
  273. }
  274.  
  275. void LineDesc::Reset()
  276. {
  277.     lnAscent= lnHeight= 0;
  278. }
  279.  
  280. void LineDesc::Max(Font *f)
  281. {
  282.     int a= Math::Max(f->Ascender(), lnAscent);
  283.     int d= Math::Max(lnHeight-lnAscent, f->Spacing()-f->Ascender());
  284.     lnAscent= a;     
  285.     lnHeight= a+d;
  286. }
  287.  
  288. void LineDesc::Max(LineDesc ld)
  289.     int a= Math::Max(ld.lnAscent, lnAscent);
  290.     int d= Math::Max(lnHeight-lnAscent, ld.lnHeight - ld.lnAscent);
  291.     lnAscent= a;     
  292.     lnHeight= a+d;
  293. }
  294.  
  295. void LineDesc::Max(int ascent, int height)
  296. {
  297.     int a= Math::Max(ascent, lnAscent);
  298.     int d= Math::Max(height-ascent, lnHeight-lnAscent);
  299.     lnAscent= a;     
  300.     lnHeight= a+d;
  301. }    
  302.  
  303. //---- class LineMark ----------------------------------------------------------
  304.  
  305. NewMetaImpl0(LineMark, Mark);
  306.  
  307. int LineMark_lineChanged;
  308.  
  309. LineMark::LineMark(
  310.     LineDesc ldesc, int pos, int len, eMarkState s
  311. ) : Mark(pos, len, s)
  312. {
  313.     ld= ldesc; 
  314. }
  315.  
  316. LineMark::LineMark() 
  317. {
  318. }
  319.  
  320. void LineMark::Copy(LineMark *m)
  321. {
  322.     Mark::ChangeMark(m->pos, m->len, m->state); 
  323.     ld= m->ld;
  324. }
  325.  
  326. void LineMark::ChangeMark( int pos, int len, LineDesc ldesc, eMarkState s)
  327. {
  328.     Mark::ChangeMark(pos, len, s); 
  329.     ld= ldesc;
  330. }
  331.  
  332. bool LineMark::IsDifferent(LineMark *m)
  333. {
  334.     return pos != m->pos
  335.        || len != m->len 
  336.        || !ld.IsEqual(m->ld)
  337.        || m->state != eStateNone
  338.        || state != eStateNone; 
  339. }
  340.  
  341.